#include "light.h"
#include "sdl_screen.h"
#include "settings.h"


Light::Light(const glm::vec3& pos, float intensity)
: _pos(pos)
, _color(intensity)
, _shadowAlpha(SHADOW_ALPHA)
{
	sdl::Event::getInstance()->addListener(this);
}


glm::vec3 Light::calcColor(const Intersection& i, const Scene* scene)
{
	const glm::vec3& lightVector = _pos - i.point;
	const glm::vec3& normLightVector = glm::normalize(lightVector);
	float diffuse = glm::dot(i.triangle->getNormal(), normLightVector);
	float distance = glm::length(lightVector);

	const glm::vec3& col =
		_color * std::max(diffuse, 0.f) / (float)(4 * M_PI * distance * distance);

	if (scene) {
		// Apply shadow
		Intersection si;
		if (scene->closestIntersect(Ray(i.point, normLightVector), &si) &&
			si.distance < distance)
		{
			return _shadowAlpha * col;
		}
	}
	return col;
}


void Light::on(EventListener::NewEvent, const SDL_Event* e) throw()
{
	if (e->type != SDL_KEYDOWN)
		return;
	switch (e->key.keysym.sym) {
	case LIGHT_MOVE_FORW:
		_pos.z += LIGHT_MOVE_STEP;
		break;
	case LIGHT_MOVE_BACK:
		_pos.z -= LIGHT_MOVE_STEP;
		break;
	case LIGHT_MOVE_LEFT:
		_pos.x -= LIGHT_MOVE_STEP;
		break;
	case LIGHT_MOVE_RIGHT:
		_pos.x += LIGHT_MOVE_STEP;
		break;
	case LIGHT_MOVE_UP:
		_pos.y -= LIGHT_MOVE_STEP;
		break;
	case LIGHT_MOVE_DOWN:
		_pos.y += LIGHT_MOVE_STEP;
		break;
	default:
		return;
	}
	// Update screen
	sdl::Screen::getInstance()->update();
}

